package com.youlu.campus.common.utils;

import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.BCUtil;
import cn.hutool.crypto.ECKeyUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import cn.hutool.crypto.SmUtil;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.signers.PlainDSAEncoding;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;

import java.security.PublicKey;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

@Slf4j
public class SM2CryptUtils {
    /**
     * 公钥常量
     */
    public static final String KEY_PUBLIC_KEY = "publicKey";
    /**
     * 私钥返回值常量
     */
    public static final String KEY_PRIVATE_KEY = "privateKey";

    /**
     * 生成秘钥对
     *
     * @return
     */
    public static Map<String, String> createSM2Key() {
        SM2 sm2 = SmUtil.sm2();
        sm2.setMode(SM2Engine.Mode.C1C3C2);
        String privateKey = HexUtil.encodeHexStr(BCUtil.encodeECPrivateKey(sm2.getPrivateKey()));
        String publicKey = HexUtil.encodeHexStr(((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false));
        Map<String, String> keys = new HashMap<>();
//        keys.put(publicKey,privateKey);
        keys.put(KEY_PUBLIC_KEY, publicKey);
        keys.put(KEY_PRIVATE_KEY, privateKey);
        return keys;
    }

    /**
     * 加密
     *
     * @param data
     * @param publicKey
     * @return
     */
    public static String encrypt(String data, String publicKey) {
        String publicKeyTmp = publicKey;
        if (publicKey.length() == 130) {
            //这里需要去掉开始第一个字节 第一个字节表示标记
            publicKeyTmp = publicKey.substring(2);
        }
        String xhex = publicKeyTmp.substring(0, 64);
        String yhex = publicKeyTmp.substring(64, 128);
        ECPublicKeyParameters ecPublicKeyParameters = BCUtil.toSm2Params(xhex, yhex);
        //创建sm2 对象
        SM2 sm2 = new SM2(null, ecPublicKeyParameters);
        sm2.usePlainEncoding();
        sm2.setMode(SM2Engine.Mode.C1C3C2);
        String hex = sm2.encryptHex(data, KeyType.PublicKey);
        return hex;

    }

    /**
     * 解密
     *
     * @param data
     * @param privateKey
     * @return
     */
    public static String decrypt(String data, String privateKey) {
        SM2 sm2 = new SM2(ECKeyUtil.toSm2PrivateParams(privateKey), null);
        sm2.setMode(SM2Engine.Mode.C1C3C2);
        sm2.setEncoding(new PlainDSAEncoding());
        String encryptStr = sm2.decryptStr(data, KeyType.PrivateKey);
        return encryptStr;
    }
}
